/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.biz.modular.cabinetlinkman.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fhs.trans.service.impl.TransService;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.auth.core.util.StpClientUtil;
import vip.xiaonuo.biz.modular.cabinetdoor.entity.BizCabinetDoor;
import vip.xiaonuo.biz.modular.cabinetdoor.service.BizCabinetDoorService;
import vip.xiaonuo.biz.modular.cabinetinfo.entity.BizCabinetInfo;
import vip.xiaonuo.biz.modular.cabinetinfo.service.BizCabinetInfoService;
import vip.xiaonuo.biz.modular.cabinetlinkman.entity.BizCabinetLinkman;
import vip.xiaonuo.biz.modular.cabinetlinkman.mapper.BizCabinetLinkmanMapper;
import vip.xiaonuo.biz.modular.cabinetlinkman.param.BizCabinetLinkmanAddParam;
import vip.xiaonuo.biz.modular.cabinetlinkman.param.BizCabinetLinkmanEditParam;
import vip.xiaonuo.biz.modular.cabinetlinkman.param.BizCabinetLinkmanIdParam;
import vip.xiaonuo.biz.modular.cabinetlinkman.param.BizCabinetLinkmanPageParam;
import vip.xiaonuo.biz.modular.cabinetlinkman.result.BizCabinetLinkmanVO;
import vip.xiaonuo.biz.modular.cabinetlinkman.result.ClientCabinetLinkmanVO;
import vip.xiaonuo.biz.modular.cabinetlinkman.service.BizCabinetLinkmanService;
import vip.xiaonuo.biz.modular.cabinetpermission.service.BizCabinetPermissionUtil;
import vip.xiaonuo.biz.modular.org.entity.BizOrg;
import vip.xiaonuo.biz.modular.org.service.BizOrgService;
import vip.xiaonuo.biz.modular.relation.enums.BizRelationCategoryEnum;
import vip.xiaonuo.biz.modular.relation.service.BizRelationService;
import vip.xiaonuo.biz.modular.user.entity.BizUser;
import vip.xiaonuo.biz.modular.user.service.BizUserService;
import vip.xiaonuo.common.exception.CommonException;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 柜子联系人Service接口实现类
 *
 * @author kongxm
 * @date 2022/11/12 21:19
 **/
@Service
public class BizCabinetLinkmanServiceImpl extends ServiceImpl<BizCabinetLinkmanMapper, BizCabinetLinkman> implements BizCabinetLinkmanService {
    @Resource
    private BizCabinetInfoService bizCabinetInfoService;
    @Resource
    private BizCabinetDoorService bizCabinetDoorService;
    @Resource
    private TransService transService;
    @Resource
    private BizUserService bizUserService;
    @Resource
    private BizCabinetPermissionUtil bizCabinetPermissionUtil;
    @Resource
    private BizRelationService bizRelationService;
    @Resource
    private BizOrgService bizOrgService;

    @Override
    public Page<BizCabinetLinkmanVO> page(BizCabinetLinkmanPageParam param) {
        return getBaseMapper().page(Page.of(param.getCurrent(), param.getSize()), param);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(BizCabinetLinkmanAddParam param) {
        bizCabinetPermissionUtil.hasPermission(param.getCabinetGroupId(), param.getCabinetInfoId(), null);
        param.getUserIds().forEach(userId -> {
            BizCabinetLinkman bizCabinetLinkman = new BizCabinetLinkman();
            bizCabinetLinkman.setUserId(userId);
            bizCabinetLinkman.setIdentify(param.getIdentify());
            bizCabinetLinkman.setCabinetGroupId(param.getCabinetGroupId());
            bizCabinetLinkman.setCabinetInfoId(param.getCabinetInfoId());
            if (StringUtils.isNotEmpty(param.getCabinetGroupId())) { // throw error if exist
                BizCabinetLinkman existObj = getOne(new LambdaQueryWrapper<BizCabinetLinkman>()
                        .eq(BizCabinetLinkman::getCabinetGroupId, param.getCabinetGroupId())
                        .eq(BizCabinetLinkman::getUserId, userId)
                        .eq(BizCabinetLinkman::getDeleteFlag, "NOT_DELETE").last("limit 1"));
                if (existObj != null) {
                    BizUser bizUser = bizUserService.getById(userId);
                    if (bizUser != null) {
                        throw new CommonException(String.format("%s已存在", bizUser.getName()));
                    }
                }
            } else if (StringUtils.isNotEmpty(param.getCabinetInfoId())) {// throw error if exist
                BizCabinetLinkman existObj = getOne(new LambdaQueryWrapper<BizCabinetLinkman>()
                        .eq(BizCabinetLinkman::getCabinetInfoId, param.getCabinetInfoId())
                        .eq(BizCabinetLinkman::getUserId, userId)
                        .eq(BizCabinetLinkman::getDeleteFlag, "NOT_DELETE").last("limit 1"));
                if (existObj != null) {
                    BizUser bizUser = bizUserService.getById(userId);
                    if (bizUser != null) {
                        throw new CommonException(String.format("%s已存在", bizUser.getName()));
                    }
                }
            }
            this.save(bizCabinetLinkman);
        });
    }

    @Override
    public void edit(BizCabinetLinkmanEditParam param) {
        BizCabinetLinkman bizCabinetLinkman = this.queryEntity(param.getId());
        bizCabinetPermissionUtil.hasPermission(bizCabinetLinkman.getCabinetGroupId(), bizCabinetLinkman.getCabinetInfoId(), null);
        BeanUtil.copyProperties(param, bizCabinetLinkman);
        this.updateById(bizCabinetLinkman);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<BizCabinetLinkmanIdParam> bizCabinetLinkmanIdParamList) {
        bizCabinetLinkmanIdParamList.forEach(item -> {
            BizCabinetLinkman bizCabinetLinkman = this.queryEntity(item.getId());
            bizCabinetPermissionUtil.hasPermission(bizCabinetLinkman.getCabinetGroupId(), bizCabinetLinkman.getCabinetInfoId(), null);
        });
        // 执行删除
        this.removeByIds(CollStreamUtil.toList(bizCabinetLinkmanIdParamList, BizCabinetLinkmanIdParam::getId));
    }

    @Override
    public BizCabinetLinkman detail(BizCabinetLinkmanIdParam bizCabinetLinkmanIdParam) {
        return this.queryEntity(bizCabinetLinkmanIdParam.getId());
    }

    @Override
    public BizCabinetLinkman queryEntity(String id) {
        BizCabinetLinkman bizCabinetLinkman = this.getById(id);
        if (ObjectUtil.isEmpty(bizCabinetLinkman)) {
            throw new CommonException("柜子联系人不存在，id值为：{}", id);
        }
        return bizCabinetLinkman;
    }

    @Override
    public List<ClientCabinetLinkmanVO> listForClient(String cabinetDoorId) {
        Assert.notBlank(cabinetDoorId, "柜门id不能为空");
        List<ClientCabinetLinkmanVO> resultList = new ArrayList<>(2);

        BizCabinetDoor bizCabinetDoor = bizCabinetDoorService.getById(cabinetDoorId);
        if (bizCabinetDoor == null || StringUtils.isEmpty(bizCabinetDoor.getCabinetInfoId())) return resultList;

        BizCabinetInfo bizCabinetInfo = bizCabinetInfoService.getById(bizCabinetDoor.getCabinetInfoId());
        if (bizCabinetInfo == null) return resultList;
        // 取柜子联系人
        getBaseMapper().listForClient(null, bizCabinetInfo.getId())
                .forEach(item -> {
                    ClientCabinetLinkmanVO linkman = BeanUtil.copyProperties(item, ClientCabinetLinkmanVO.class);
                    resultList.add(linkman);
                });

        if (bizCabinetInfo.getCabinetGroupId() == null) return resultList;
        // 取组柜联系人
        getBaseMapper().listForClient(bizCabinetInfo.getCabinetGroupId(), null)
                .forEach(item -> {
                    //去掉重复的数据，身份+用户 一样为重复
                    boolean exist = resultList.stream().anyMatch(record -> record.getJobNumber()
                            .equals(item.getJobNumber()) && record.getIdentify()
                            .equals(item.getIdentify()));
                    if (exist) return;
                    ClientCabinetLinkmanVO linkman = BeanUtil.copyProperties(item, ClientCabinetLinkmanVO.class);
                    resultList.add(linkman);
                });

        // 一次性把机构查出来
        List<BizOrg> bizOrgList = bizOrgService.list(new LambdaQueryWrapper<BizOrg>().select(BizOrg::getId, BizOrg::getName));
        //柜子管理员
        List<String> cabinetInfoAdminIds = bizRelationService.getRelationTargetIdListByObjectIdAndCategory(
                bizCabinetInfo.getId(),
                BizRelationCategoryEnum.BIZ_RELATION_CABINET_INFO_AND_ADMIN_USER.getValue());
        resultList.addAll(getAdminList(cabinetInfoAdminIds, bizOrgList));
        //柜门管理员
        List<String> cabinetDoorAdminIds = bizRelationService.getRelationTargetIdListByObjectIdAndCategory(
                bizCabinetInfo.getId(),
                BizRelationCategoryEnum.BIZ_RELATION_CABINET_DOOR_AND_ADMIN_USER.getValue());
        resultList.addAll(getAdminList(cabinetDoorAdminIds, bizOrgList));
        transService.transBatch(resultList);
        return resultList;
    }

    private List<ClientCabinetLinkmanVO> getAdminList(List<String> adminIds, List<BizOrg> bizOrgList) {
        if (CollectionUtil.isEmpty(adminIds)) return ListUtil.empty();
        return bizUserService.list(new LambdaQueryWrapper<BizUser>()
                .select(BizUser::getUserNo, BizUser::getName, BizUser::getPhone, BizUser::getOrgId, BizUser::getOfficeAdd)
                .in(BizUser::getId, adminIds))
                .stream().map(item -> {
                    ClientCabinetLinkmanVO linkman = new ClientCabinetLinkmanVO();
                    linkman.setJobNumber(item.getUserNo());
                    linkman.setUserName(item.getName());
                    linkman.setMobile(item.getPhone());
                    bizOrgList.stream().filter(org -> org.getId().equals(item.getOrgId())).findAny()
                            .ifPresent(org -> linkman.setOrgName(org.getName()));
                    linkman.setOfficeAddress(item.getOfficeAdd());
                    return linkman;
                }).collect(Collectors.toList());
    }
}
